package ThreadDemo;

import javax.swing.tree.TreeNode;
import java.util.Scanner;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 34255
 * Date: 2024-10-20
 * Time: 10:34
 */
//wait()等待 notify()通知 方法的使用
public class Demo20 {
    public static void main(String[] args) {
        Object o = new Object();
        Thread t1 = new Thread(() -> {
            System.out.println("t1 wait()使用之前");
            synchronized(o){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t1 wait()使用之后");
        });

        Thread t2 = new Thread(() -> {
            System.out.println("t2 wait()使用之前");
            synchronized (o){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t2 wait()使用之后");
        });

        Thread t3 = new Thread(() -> {
            System.out.println("请输入值随机唤醒所有wait()");
            Scanner scanner = new Scanner(System.in);
            scanner.nextInt();
            synchronized(o){
                o.notifyAll();//notifyAll()虽然能够唤醒所有用一个锁对象的wait()方法，但是这并不是并行执行的
                //而是串行执行，当一个wait()拿到锁对象之后，由于锁的互斥性，所以其他线程就只能阻塞等待，等到线程
                //释放锁对象，其他线程在拿着该锁对象唤醒wait()
            }
        });

        t1.start();
        t2.start();
        t3.start();
    }
    public static void main4(String[] args) {
        Object o = new Object();
        Thread t1 = new Thread(() -> {
            System.out.println("t1 wait()使用之前");
            synchronized(o){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t1 wait()使用之后");
        });

        Thread t2 = new Thread(() -> {
            System.out.println("t2 wait()使用之前");
            synchronized (o){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t2 wait()使用之后");
        });

        Thread t3 = new Thread(() -> {
            System.out.println("请输入值随机唤醒一个wait()");
            Scanner scanner = new Scanner(System.in);
            scanner.nextInt();
            synchronized(o){
                o.notify();//一个notify()每次只能随机唤醒一个wait()方法，N个wait()需要N个notify()方法唤醒
            }
        });

        Thread t4 = new Thread(() -> {
            System.out.println("请输入值,唤醒另外一个wait()");
            Scanner scanner = new Scanner(System.in);
            scanner.nextInt();
            synchronized(o){
                o.notify();//一个notify()每次只能随机唤醒一个wait()方法，N个wait()需要N个notify()方法唤醒
            }
        });
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
    public static void main3(String[] args) throws InterruptedException {
        Object o = new Object();
        Thread t1 = new Thread(() -> {
            System.out.println("wait()使用之前");
            synchronized(o){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("wait()使用之后");
        });

        Thread t2 = new Thread(() -> {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入值，通知唤醒wait()");
            scanner.next();
            synchronized(o){
                o.notify();
            }
        });

        t1.start();
        t2.start();
    }
    public static void main2(String[] args) throws InterruptedException {
        //创建锁对象
        Object locker = new Object();
        System.out.println("wait()使用之前");
        synchronized(locker){//锁对象必须是同一个
            locker.wait();
        }
        System.out.println("wait()使用之后");
    }
    public static void main1(String[] args) throws InterruptedException {
        //创建锁对象
        Object locker = new Object();
        System.out.println("wait()使用之前");
        locker.wait();//使用wait()方法，其第一件事就是释放锁对象，所以使用wait()方法必须处于加锁状态
        //这样才能有锁被wait()释放，否则报错，且被加锁的对象和wait()的对象必需是同一个
        System.out.println("wait()使用之后");
    }
}
